package com.emperor.employee.app;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;

import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Expression;
import org.hibernate.criterion.Order;
import org.vafada.swtcalendar.SWTCalendarDialog;
import org.vafada.swtcalendar.SWTCalendarEvent;
import org.vafada.swtcalendar.SWTCalendarListener;

import com.emperor.core.app.App;
import com.emperor.core.app.AppConstant;

import com.emperor.core.app.AppBase;
import com.emperor.customer.app.CustomerAppCtrl;
import com.emperor.employee.logic.Employee;
import com.emperor.employee.logic.EmployeeModel;
import com.emperor.role.logic.Role;
import com.emperor.role.logic.RoleModel;
import com.emperor.user.logic.User;
import com.emperor.user.logic.UserModel;
import com.emperor.util.DateFormatter;
import com.emperor.util.HibernateUtil;
import com.emperor.util.KalendarDialog;
import com.swtdesigner.SWTResourceManager;

public class EmployeeAppNew extends AppBase implements App {

	private Combo combo;
	protected Shell shell;
	public static Logger log = Logger.getLogger(EmployeeAppNew.class);
	private SimpleDateFormat sdf = new SimpleDateFormat(DateFormatter.YYYYMMDD);
	protected String code;
	protected Integer codeid;

	public EmployeeAppNew() {
		super();
	}

	public EmployeeAppNew(Map<String, Object> params) {
		super();
		this.params = params;
	}

	/**
	 * Launch the application
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			EmployeeAppNew window = new EmployeeAppNew();
			window.open();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Open the window
	 */
	public void open() {
		final Display display = Display.getDefault();
		createContents();
		shell.open();
		shell.layout();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
	}

	/**
	 * Create contents of the window
	 */
	protected void createContents() {
		shell = new Shell();
		shell.setBackgroundImage(SWTResourceManager.getImage(
				EmployeeAppNew.class, "/img/main.jpg"));
		shell.setImage(SWTResourceManager.getImage(EmployeeAppNew.class,
				"/img/iMac OSX.png"));
		shell.setFont(SWTResourceManager.getFont("", 12, SWT.NONE));
		shell.setBackgroundMode(SWT.INHERIT_DEFAULT);
		shell.setSize(1280, 800);
		shell.setText("New Employee Form");

		initScreen(shell, getParams());

		final Composite composite = new Composite(shell, SWT.NONE);
		composite.setFont(SWTResourceManager.getFont("", 12, SWT.NONE));
		composite.setBounds(0, 50, 892, 483);

		final Label nameLabel = new Label(composite, SWT.NONE);
		nameLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		nameLabel.setText("Name");
		nameLabel.setBounds(10, 184, 45, 20);

		final Label codeLabel = new Label(composite, SWT.NONE);
		codeLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		codeLabel.setText("Code");
		codeLabel.setBounds(10, 218, 40, 20);

		final Label icLabel = new Label(composite, SWT.NONE);
		icLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		icLabel.setText("IC");
		icLabel.setBounds(10, 254, 20, 20);

		final Label birthdateLabel = new Label(composite, SWT.NONE);
		birthdateLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		birthdateLabel.setText("Birthdate");
		birthdateLabel.setBounds(10, 290, 65, 20);

		final Label phoneLabel = new Label(composite, SWT.NONE);
		phoneLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		phoneLabel.setText("Phone");
		phoneLabel.setBounds(10, 326, 50, 20);

		final Label emailLabel = new Label(composite, SWT.NONE);
		emailLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		emailLabel.setText("Email");
		emailLabel.setBounds(10, 362, 40, 20);

		final Label addressLabel = new Label(composite, SWT.NONE);
		addressLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		addressLabel.setText("Address");
		addressLabel.setBounds(10, 398, 60, 20);

		final Label usernameLabel = new Label(composite, SWT.NONE);
		usernameLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		usernameLabel.setText("Username");
		usernameLabel.setBounds(10, 44, 75, 20);

		final Label passwordLabel = new Label(composite, SWT.NONE);
		passwordLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		passwordLabel.setText("Password");
		passwordLabel.setBounds(10, 80, 70, 20);

		final Text text = new Text(composite, SWT.BORDER);
		text.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		text.setToolTipText("user_username");
		text.setBounds(152, 41, 300, 30);

		final Text text_1 = new Text(composite, SWT.BORDER | SWT.PASSWORD);
		text_1.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		text_1.setToolTipText("user_password");
		text_1.setBounds(152, 77, 300, 30);

		final Text text_2 = new Text(composite, SWT.BORDER | SWT.PASSWORD);
		text_2.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		text_2.setToolTipText("user_cpassword");
		text_2.setBounds(152, 113, 300, 30);

		final Text text_3 = new Text(composite, SWT.BORDER);
		text_3.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		text_3.setToolTipText("emp_name");
		text_3.setBounds(152, 181, 300, 30);

		final Text text_4 = new Text(composite, SWT.BORDER);
		text_4.setEditable(false);
		text_4.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		text_4.setToolTipText("emp_code");
		text_4.setBounds(152, 215, 300, 30);

		final Text text_5 = new Text(composite, SWT.BORDER);
		text_5.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		text_5.setToolTipText("emp_ic");
		text_5.setBounds(152, 251, 300, 30);

		final Text text_7 = new Text(composite, SWT.BORDER);
		text_7.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		text_7.setToolTipText("emp_birthdate");
		text_7.setBounds(152, 287, 205, 30);

		final Text text_6 = new Text(composite, SWT.BORDER);
		text_6.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		text_6.setToolTipText("emp_phone");
		text_6.setBounds(152, 323, 208, 30);

		final Text text_8 = new Text(composite, SWT.BORDER);
		text_8.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		text_8.setToolTipText("emp_email");
		text_8.setBounds(152, 359, 300, 30);

		final Label confirmPasswordLabel = new Label(composite, SWT.NONE);
		confirmPasswordLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		confirmPasswordLabel.setText("Confirm Password");
		confirmPasswordLabel.setBounds(10, 116, 130, 20);

		final Text text_9 = new Text(composite, SWT.WRAP | SWT.V_SCROLL
				| SWT.MULTI | SWT.BORDER);
		text_9.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		text_9.setToolTipText("emp_address");
		text_9.setBounds(152, 395, 300, 74);

		final Label messageLabel = new Label(composite, SWT.NONE);
		messageLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		messageLabel.setBounds(10, 10, 705, 25);
		messageLabel.setText("Please fill in the New Employee Form below");

		final Button pickDateButton = new Button(composite, SWT.NONE);
		pickDateButton.setImage(SWTResourceManager.getImage(
				EmployeeAppNew.class, "/img/Calendar.png"));
		pickDateButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				pickDate(getShell(), text_7);
			}
		});
		pickDateButton.setBounds(364, 286, 30, 30);

		final Button addNewEmployeeButton = new Button(shell, SWT.NONE);
		addNewEmployeeButton.setImage(SWTResourceManager.getImage(
				EmployeeAppNew.class, "/img/Save.png"));
		addNewEmployeeButton.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		addNewEmployeeButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				try {
					User user = new UserModel();
					Employee employee = new EmployeeModel();

					user = (User) setModel(composite, "user", user);
					employee = (Employee) setModel(composite, "emp", employee);

					log.debug(user.getClass().getSimpleName() + " : "
							+ user.getValues().toString());
					log.debug(employee.getClass().getSimpleName() + " : "
							+ employee.getValues().toString());

					List<String> errors = validateForm(user, employee, text_2
							.getText(), combo.getText());
					if (errors.isEmpty()) {
						user = (User) preAdd(user, getParams());
						employee = (Employee) preAdd(employee, getParams());

						user.setRole(doRetrieveRoleByName(combo.getText()));
						user.setStatus(AppConstant.STATUS_ACTIVE);
						employee.setStatus(AppConstant.STATUS_ACTIVE);
						employee.setCode(getCode());
						employee.setCodeid(getCodeid());

						int rowCount = doAdd(employee, user);

						if (rowCount >= 2) {
							message(getShell(), "Save Success.",
									"Employee added successfully.");

							getParams().put(AppConstant.APPCTRL,
									EmployeeAppCtrl.EMP_CTRL);
							getParams().put(AppConstant.ACTION,
									EmployeeAppCtrl.EMP_ENQ);
							getShell().close();
						} else {
							message(getShell(), "Save Error.",
									"Unable to add employee.", SWT.ICON_ERROR
											| SWT.OK);
						}
					} else {
						message(getShell(), "Save Error.", errors,
								SWT.ICON_ERROR | SWT.OK);
					}

				} catch (Exception ex) {
					message(getShell(), "Save Error.", ex.getMessage());
					log.error(ex.getMessage(), ex);
				}
			}
		});
		addNewEmployeeButton.setText("Save");
		addNewEmployeeButton.setBounds(152, 539, 75, 30);

		final Button resetButton = new Button(shell, SWT.NONE);
		resetButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				getShell().close();
			}
		});
		resetButton.setImage(SWTResourceManager.getImage(EmployeeAppNew.class,
				"/img/Refresh.png"));
		resetButton.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		resetButton.setText("Reset");
		resetButton.setBounds(233, 540, 80, 30);

		final Label roleaLabel = new Label(composite, SWT.NONE);
		roleaLabel.setBounds(481, 44, 75, 20);
		roleaLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		roleaLabel.setText("Role");

		combo = new Combo(composite, SWT.READ_ONLY);
		combo.select(0);
		combo.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		combo.setBounds(575, 41, 300, 28);
		buildStandardMenu(getShell(), getParams(), EmployeeAppCtrl.EMP_CTRL,
				EmployeeAppCtrl.EMP_ENQ);
		//

		setCode(generateCode(generateCodeid()));
		text_4.setText(getCode());
		populateRole(combo);
	}

	public static List<String> validateForm(User user, Employee employee,
			String cpassword, String role) throws Exception {
		List<String> errors = new ArrayList<String>();

		if (StringUtils.isEmpty(user.getUsername())) {
			errors.add("Username cannot be empty.");
		}
		if (StringUtils.isEmpty(user.getPassword())) {
			errors.add("Password cannot be empty.");
		}
		if (StringUtils.isEmpty(cpassword)) {
			errors.add("Confirm password cannot be empty.");
		}
		if (!cpassword.trim().equals(user.getPassword())) {
			errors.add("Password and confirm password does not match.");
		}
		if (StringUtils.isEmpty(employee.getAddress())) {
			errors.add("Address cannot be empty.");
		}
		if (StringUtils.isEmpty(employee.getCode())) {
			errors.add("Code cannot be empty.");
		}
		if (StringUtils.isEmpty(employee.getEmail())) {
			errors.add("Email cannot be empty.");
		}
		if (StringUtils.isEmpty(employee.getIc())) {
			errors.add("IC cannot be empty.");
		}
		if (StringUtils.isEmpty(employee.getName())) {
			errors.add("Name cannot be empty.");
		}
		if (StringUtils.isEmpty(employee.getPhone())) {
			errors.add("Phone cannot be empty.");
		}
		if (employee.getBirthdate() == null) {
			errors.add("Birthdate cannot be empty.");
		}

		if (StringUtils.isEmpty(role)) {
			errors.add("Role cannot be empty.");
		}

		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		List<User> users = new ArrayList<User>();
		Criteria cris = session.createCriteria(UserModel.class).add(
				Expression.eq(User.FLD_USERNAME, user.getUsername()));
		if (user.getId() != null) {
			cris.add(Expression.ne(User.FLD_ID, user.getId()));
		}
		users = cris.list();
		if (users != null && !users.isEmpty()) {
			errors.add("Duplicate username. Please use another username.");
		}

		List<Employee> employees = new ArrayList<Employee>();
		cris = session.createCriteria(EmployeeModel.class).add(
				Expression.eq(Employee.FLD_NAME, employee.getName()));
		if (employee.getId() != null) {
			cris.add(Expression.ne(Employee.FLD_ID, employee.getId()));
		}
		employees = cris.list();
		if (employees != null && !employees.isEmpty()) {
			errors.add("Duplicate name. Please use another name.");
		}

		return errors;
	}

	public Shell getShell() {
		return shell;
	}

	private int doAdd(Employee employee, User user) throws Exception {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		int count = 0;
		try {
			session.beginTransaction();

			session.save(employee);
			log.debug(employee.getClass().getSimpleName() + " : "
					+ employee.getValues().toString());

			if (employee.getId() != null) {
				count++;
				user.setEmployee(employee);
				session.save(user);
				log.debug(user.getClass().getSimpleName() + " : "
						+ user.getValues().toString());
				count++;
			}

			session.getTransaction().commit();
		} catch (Exception e) {
			session.getTransaction().rollback();
			throw e;
		}
		return count;
	}

	private String generateCode(Integer codeid) {
		StringBuffer sb = new StringBuffer();
		try {
			sb.append("E");
			if (codeid != null) {
				sb.append(codeid.toString());
			}
		} catch (Exception e) {
			log.error("Unable to generate employee code.", e);
		}
		return sb.toString();
	}

	private Integer generateCodeid() {
		Integer codeid = new Integer(Employee.START_CODEID);
		try {
			Session session = HibernateUtil.getSessionFactory()
					.getCurrentSession();
			List<Employee> employees = session.createCriteria(
					EmployeeModel.class).addOrder(Order.desc(Employee.FLD_ID))
					.setMaxResults(1).list();

			if (employees != null && !employees.isEmpty()) {
				Employee employee = employees.get(0);
				codeid = employee.getCodeid().intValue() + 1;
			}

			setCodeid(codeid);
		} catch (Exception e) {
			log.error("Unable to generate codeid.", e);
		}
		return codeid;
	}

	private void populateRole(Combo combo) {
		try {
			Session session = HibernateUtil.getSessionFactory()
					.getCurrentSession();
			session.beginTransaction();
			List<Role> roles = session.createCriteria(RoleModel.class).add(
					Expression.eq(Role.FLD_STATUS, AppConstant.STATUS_ACTIVE))
					.list();
			if (roles != null && !roles.isEmpty()) {
				combo.removeAll();
				for (Iterator<Role> iter = roles.iterator(); iter.hasNext();) {
					Role role = iter.next();
					combo.add(role.getName());
				}
				combo.select(0);
			}
		} catch (Exception e) {
			log.error("Unable to populate role.", e);
		}
	}

	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		if (code != null) {
			if (code instanceof String) {
				this.code = (String) code;
			} else {
				try {
					this.code = code.toString();
				} catch (Exception e) {
				}
			}
		}
	}

	private Role doRetrieveRoleByName(String name) {
		Role role = null;
		try {
			Session session = HibernateUtil.getSessionFactory()
					.getCurrentSession();
			session.beginTransaction();

			List<Role> roles = session.createCriteria(RoleModel.class).add(
					Expression.eq(Role.FLD_NAME, name)).setMaxResults(1).list();
			if (roles != null && !roles.isEmpty()) {
				role = roles.get(0);
			}
		} catch (Exception e) {
			log.error("Unable to retrieve role by name.", e);
		}
		return role;
	}

	public Integer getCodeid() {
		return codeid;
	}

	public void setCodeid(Object codeid) {
		if (codeid != null) {
			if (codeid instanceof Integer) {
				this.codeid = (Integer) codeid;
			} else {
				try {
					this.codeid = new Integer(codeid.toString());
				} catch (Exception e) {
				}
			}
		}
	}
}
